package cn.edu.zufe.mjt.insight;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author 蒙锦涛
 * @date 2025/5/19
 */


public class MyThreadPool {

    private int corePollSize;
    private int maxPoolSize;
    private int timeOut;
    private TimeUnit timeUnit;
    public BlockingQueue<Runnable> blockingQueue;
    private RejectHandle rejectHandle;


    public MyThreadPool(int corePollSize, int maxPoolSize, int timeOut, TimeUnit timeUnit,BlockingQueue<Runnable> blockingQueue, RejectHandle rejectHandle) {
        this.corePollSize = corePollSize;
        this.maxPoolSize = maxPoolSize;
        this.timeOut = timeOut;
        this.timeUnit = timeUnit;
        this.blockingQueue = blockingQueue;
        this.rejectHandle = rejectHandle;
    }


    List<Thread> coreList = new ArrayList<>();

    List<Thread> supportList = new ArrayList<>();

    // 判断 coreList 有多少元素，如果小于corePollSize，就创建新的线程
    void execute(Runnable command) {
        //TIP  这里判断元素和添加元素的操作不是原子的，所以是存在线程安全问题的
        // 要解决问题可以使用原子操作，或者CAS的原子变量，或者锁
        if (coreList.size() < corePollSize) {
            Thread thread = new CoreThread(command);
            coreList.add(thread);
            thread.start();
            return;
        }
        if (blockingQueue.offer(command)) {
            return;
        }
        if (coreList.size() + supportList.size() < maxPoolSize) {
            Thread thread = new SupportThread(command);
            supportList.add(thread);
            thread.start();
            return;
        }
        if (!blockingQueue.offer(command)) {
            rejectHandle.reject(command,this);
        }
    }

    public Integer getCorePoolSize() {
        return coreList.size();
    }

    public Integer getActiveCount() {
        return coreList.size() + supportList.size();
    }


    class CoreThread extends Thread {

        private final Runnable firstTask;

        public CoreThread(Runnable firstTask) {
            this.firstTask = firstTask;
            this.setName("CoreThread-" + coreList.size());
        }

        @Override
        public void run() {
            firstTask.run();
            while (true) {
                try {
                    Runnable command = blockingQueue.take();
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    class SupportThread extends Thread {
        private final Runnable firstTask;

        public SupportThread(Runnable firstTask) {
            this.firstTask = firstTask;
            this.setName("SupportThread-" + supportList.size());
        }

        @Override
        public void run() {
            firstTask.run();
            while (true) {
                try {
                    Runnable command = blockingQueue.poll(timeOut, timeUnit);
                    if (command == null) {
                        break;
                    }
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(Thread.currentThread().getName() + "线程结束了！");
            supportList.remove(Thread.currentThread());
        }
    }
}
